---
title: SAIF.Services.Appworx business rules
summary: Enumerated business rules with per-rule trigger, enforcement, and outcomes.
status: draft
owner: SAIF Documentation
last_reviewed: 2026-08-21
library: SAIF.Services.Appworx
reference_type: embedded
---

# SAIF.Services.Appworx business rules

This page captures business rules enforced by this library.

## BR-001 Environment-based portal routing to PRADT

| Field | Value |
| --- | --- |
| **Statement** | When the "use WCISDEV1 Appworx for all dev environments" flag is set, job submissions must be routed to the dedicated Appworx-hosting Oracle database (`WCISPROD` in production, `WCISDEV1` in every non-production environment) under schema `PRADT`, rather than to the caller's own data portal. |
| **Trigger** | Shared `SubmitBatchJob` invoked with `inUseWCISDEV1AppworxForAllDevEnv = True` |
| **Enforcement** | `clsRequestAppworxJob.vb`, shared `SubmitBatchJob` — `If inUseWCISDEV1AppworxForAllDevEnv Then ... lDAL = New clsMSOracleDataLayer("PRADT", "WCISPROD"|"WCISDEV1")` |
| **Outcome** | This override path has no in-repo caller — all three observed callers omit the flag, so it is currently inert in this application* |
| **SQL** | [SQL-001](sql/SQL-001-submit-appworx-job.md) |
| **Source** | `SAIF.Services.Appworx/clsRequestAppworxJob.vb` |

---

## BR-002 Production-only routing to the production Appworx database

| Field | Value |
| --- | --- |
| **Statement** | Production is the only environment that routes to the production Appworx database; every other environment value maps to the single shared development database. |
| **Trigger** | Environment evaluation inside [BR-001](#br-001-environment-based-portal-routing-to-pradt) |
| **Enforcement** | `clsRequestAppworxJob.vb` — `If AppGlobal.EnvironmentService.GetApplicationEnvironment() = ApplicationEnvironment.Prod` |
| **Outcome** | Non-production environments (dev, test, QA, staging, etc.) all share `WCISDEV1`* |
| **Source** | `SAIF.Services.Appworx/clsRequestAppworxJob.vb` |

---

## BR-003 Only populated argument slots are transmitted

| Field | Value |
| --- | --- |
| **Statement** | Only argument slots that hold a value are transmitted to the scheduler; unsupplied arguments must not be sent as parameters. |
| **Trigger** | Building the submission parameter list |
| **Enforcement** | `clsRequestAppworxJob.vb` — `If inArgN IsNot Nothing Then .ArgN = inArgN` (shared overload) and `If Not m_ArgN.IsEmpty Then DataRequest.AddParm(...)` (instance method) |
| **Outcome** | The stored procedure receives only the populated `inArgN` parameters, so positional gaps are possible (observed callers deliberately skip arg3) |
| **SQL** | [SQL-001](sql/SQL-001-submit-appworx-job.md) |
| **Source** | `SAIF.Services.Appworx/clsRequestAppworxJob.vb` |

---

## BR-004 Module, requestor, and printer are always supplied with defaults

| Field | Value |
| --- | --- |
| **Statement** | Module, requestor, and printer are always supplied on every submission; requestor defaults to `Appworx` and printer defaults to `SYSOUT` when the caller does not specify them. |
| **Trigger** | Every call to `SubmitBatchJob` |
| **Enforcement** | `clsRequestAppworxJob.vb` — field initializers `m_Requestor = "APPWORX"`, `m_Printer = "SYSOUT"`; shared-overload optional defaults `"Appworx"` / `"SYSOUT"`; unconditional `AddParm("inModule"/"inRequestor"/"inPrinter", ...)` |
| **Outcome** | The three fixed parameters are always present; `ModuleName` has no default and is the caller's responsibility (no validation exists)* |
| **SQL** | [SQL-001](sql/SQL-001-submit-appworx-job.md) |
| **Source** | `SAIF.Services.Appworx/clsRequestAppworxJob.vb` |

---

## BR-005 Submission values are length-bounded to the schedulers contract

| Field | Value |
| --- | --- |
| **Statement** | Submission values are length-bounded to the scheduler's contract: module 30, requestor 32, printer 30, and each argument 4000 characters. |
| **Trigger** | Parameter construction in the instance `SubmitBatchJob` |
| **Enforcement** | `clsRequestAppworxJob.vb` — size arguments on each `DataRequest.AddParm` call |
| **Outcome** | Values are constrained to the declared sizes by the data-access layer; over-length input behavior (truncate vs. error) is determined by the framework/provider** |
| **SQL** | [SQL-001](sql/SQL-001-submit-appworx-job.md) |
| **Source** | `SAIF.Services.Appworx/clsRequestAppworxJob.vb` |

---

## BR-006 Submission failures are wrapped and rethrown

| Field | Value |
| --- | --- |
| **Statement** | Any failure submitting a job must be surfaced to the caller as an application-level error identifying the Appworx submission, with the original exception preserved. |
| **Trigger** | Exception thrown by `DPI.ProcessPortalRequest` |
| **Enforcement** | `clsRequestAppworxJob.vb` — `Catch ex As Exception : Throw New ApplicationException("Error Submiting Appworx Job " & ex.Message, ex)` |
| **Outcome** | Caller receives an `ApplicationException` whose `InnerException` is the original fault; no logging or retry occurs in this library |
| **Source** | `SAIF.Services.Appworx/clsRequestAppworxJob.vb` |

---

## BR-007 Argument slots never carry over between submissions

| Field | Value |
| --- | --- |
| **Statement** | A job request must never carry over argument values from a previous submission. |
| **Trigger** | Construction of `clsRequestAppworxJob`, and explicitly before each shared-overload submission |
| **Enforcement** | `clsRequestAppworxJob.vb` — `InitArgs()` in `New` and in shared `SubmitBatchJob`; `clsSmartString.SetEmpty()` per slot |
| **Outcome** | All 20 slots are returned to the empty state, so only arguments set for the current submission are transmitted |
| **Source** | `SAIF.Services.Appworx/clsRequestAppworxJob.vb` |

---

## BR-008 Submission is fire-and-forget

| Field | Value |
| --- | --- |
| **Statement** | The submission is fire-and-forget: the library does not read a result, job number, or status from the scheduler. |
| **Trigger** | Every submission |
| **Enforcement** | `clsRequestAppworxJob.vb` — `RequestType = DataRequestType.NonQuery`; no output parameters registered; `vResult` never assigned |
| **Outcome** | Callers cannot correlate the submission with a scheduler job instance from this library; success means only that the procedure call did not throw* |
| **Source** | `SAIF.Services.Appworx/clsRequestAppworxJob.vb` |

## Stored procedure business rules

Rules sourced from Oracle stored procedures referenced by this library.

| Rule ID | Rule | Source | Link |
| --- | --- | --- | --- |
| PR-001 | Every job submission is assigned a unique scheduler job identifier generated by the database, never supplied by the caller. | `submit_appworx_job` | [Details](procedures/submit-appworx-job.md#business-rules) |
| PR-002 | Jobs submitted through this entry point are always standalone (top-level) jobs, never children of a master job. | `submit_appworx_job` | [Details](procedures/submit-appworx-job.md#business-rules) |
| PR-003 | Argument slots the caller does not supply are stored as empty rather than rejected — the procedure accepts a variable-length argument list. | `submit_appworx_job` | [Details](procedures/submit-appworx-job.md#business-rules) |
| PR-004 | The printer destination is accepted but not persisted by this procedure — it does not participate in the queued job row. | `submit_appworx_job` | [Details](procedures/submit-appworx-job.md#business-rules) |
| PR-005 | Module and requestor are mandatory on every submission — the procedure provides no fallback for them. | `submit_appworx_job` | [Details](procedures/submit-appworx-job.md#business-rules) |
| PR-006 | A "no data found" condition during submission is deliberately swallowed and reported as success. | `submit_appworx_job` | [Details](procedures/submit-appworx-job.md#business-rules) |
| PR-007 | All other failures are propagated unchanged to the caller; the procedure performs no compensating action and no logging. | `submit_appworx_job` | [Details](procedures/submit-appworx-job.md#business-rules) |
| PR-008 | The procedure performs no validation of the module name, requestor, printer, or argument content. | `submit_appworx_job` | [Details](procedures/submit-appworx-job.md#business-rules) |
| PR-009 | Submission does not commit — transaction control is left entirely to the caller. | `submit_appworx_job` | [Details](procedures/submit-appworx-job.md#business-rules) |

## PR-001 Every job submission is assigned a unique scheduler job identifier generated by the database, never supplied by the caller.

| Field | Value |
| --- | --- |
| **Statement** | Every job submission is assigned a unique scheduler job identifier generated by the database, never supplied by the caller. |
| **Condition** | Always, at the start of every invocation |
| **Action** | `SELECT so_max_jobid.NEXTVAL INTO v_jobid FROM DUAL;` — the sequence value is written to `JOB_QUEUE.JOBID` |
| **Source procedure** | `submit_appworx_job` |
| **Link** | [Details](procedures/submit-appworx-job.md#business-rules) |

---

## PR-002 Jobs submitted through this entry point are always standalone (top-level) jobs, never children of a master job.

| Field | Value |
| --- | --- |
| **Statement** | Jobs submitted through this entry point are always standalone (top-level) jobs, never children of a master job. |
| **Condition** | Always |
| **Action** | `MASTER_JOB_NUMBER` is inserted as the hard-coded literal `-1` |
| **Source procedure** | `submit_appworx_job` |
| **Link** | [Details](procedures/submit-appworx-job.md#business-rules) |

---

## PR-003 Argument slots the caller does not supply are stored as empty rather than rejected — the procedure accepts a variable-length argument list.

| Field | Value |
| --- | --- |
| **Statement** | Argument slots the caller does not supply are stored as empty rather than rejected — the procedure accepts a variable-length argument list. |
| **Condition** | Any of `inarg1`..`inarg20` omitted by the caller |
| **Action** | Each `inargN` formal declares `DEFAULT ''`, so the omitted slot is inserted as an empty string (Oracle stores `''` as `NULL`) into the matching `ARG_n` column |
| **Source procedure** | `submit_appworx_job` |
| **Link** | [Details](procedures/submit-appworx-job.md#business-rules) |

---

## PR-004 The printer destination is accepted but not persisted by this procedure — it does not participate in the queued job row.

| Field | Value |
| --- | --- |
| **Statement** | The printer destination is accepted but not persisted by this procedure — it does not participate in the queued job row. |
| **Condition** | Always |
| **Action** | `inprinter` is declared as a required `IN` parameter but appears nowhere in the `INSERT` column or value list; it is silently discarded** |
| **Source procedure** | `submit_appworx_job` |
| **Link** | [Details](procedures/submit-appworx-job.md#business-rules) |

---

## PR-005 Module and requestor are mandatory on every submission — the procedure provides no fallback for them.

| Field | Value |
| --- | --- |
| **Statement** | Module and requestor are mandatory on every submission — the procedure provides no fallback for them. |
| **Condition** | Always |
| **Action** | `inmodule` and `inrequestor` are declared with no `DEFAULT`, so omitting them raises `PLS-00306` at call time; the supplied values are inserted into `JOB_QUEUE.MODULE` / `JOB_QUEUE.REQUESTOR` |
| **Source procedure** | `submit_appworx_job` |
| **Link** | [Details](procedures/submit-appworx-job.md#business-rules) |

---

## PR-006 A "no data found" condition during submission is deliberately swallowed and reported as success.

| Field | Value |
| --- | --- |
| **Statement** | A "no data found" condition during submission is deliberately swallowed and reported as success. |
| **Condition** | `NO_DATA_FOUND` raised anywhere in the body |
| **Action** | `WHEN NO_DATA_FOUND THEN NULL;` — the exception is suppressed, the procedure returns normally, and the caller cannot distinguish this from a successful queue insert** |
| **Source procedure** | `submit_appworx_job` |
| **Link** | [Details](procedures/submit-appworx-job.md#business-rules) |

---

## PR-007 All other failures are propagated unchanged to the caller; the procedure performs no compensating action and no logging.

| Field | Value |
| --- | --- |
| **Statement** | All other failures are propagated unchanged to the caller; the procedure performs no compensating action and no logging. |
| **Condition** | Any exception other than `NO_DATA_FOUND` |
| **Action** | `WHEN OTHERS THEN RAISE;` — re-raised to the caller (which wraps it as an `ApplicationException` per [BR-006](#br-006-submission-failures-are-wrapped-and-rethrown)). A source comment notes logging was considered but not implemented |
| **Source procedure** | `submit_appworx_job` |
| **Link** | [Details](procedures/submit-appworx-job.md#business-rules) |

---

## PR-008 The procedure performs no validation of the module name, requestor, printer, or argument content.

| Field | Value |
| --- | --- |
| **Statement** | The procedure performs no validation of the module name, requestor, printer, or argument content. |
| **Condition** | Always |
| **Action** | No `IF`/`CASE`/constraint checks exist in the body — the only control flow is the sequence fetch, the insert, and the exception handler. Bad module names are queued and fail later in the scheduler** |
| **Source procedure** | `submit_appworx_job` |
| **Link** | [Details](procedures/submit-appworx-job.md#business-rules) |

---

## PR-009 Submission does not commit — transaction control is left entirely to the caller.

| Field | Value |
| --- | --- |
| **Statement** | Submission does not commit — transaction control is left entirely to the caller. |
| **Condition** | Always |
| **Action** | No `COMMIT`, `ROLLBACK`, `SAVEPOINT`, or `PRAGMA AUTONOMOUS_TRANSACTION` appears in the body; the queued row becomes visible to the scheduler only when the caller's transaction commits (the BOF data portal governs this)** |
| **Source procedure** | `submit_appworx_job` |
| **Link** | [Details](procedures/submit-appworx-job.md#business-rules) |

---

## Notes
- No authorization checks are performed by this library; any caller holding a valid `IDataPortalInfo` can submit any Appworx module with any arguments — enforcement is the responsibility of the calling application layer and the database account behind the data portal*.

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Database tables](database-tables.md)
- [SQL catalog](sql/index.md)
- [Procedures](procedures/index.md)
- [API reference](api/index.md)

## Sources
- `SAIF.Services.Appworx/clsRequestAppworxJob.vb`
